/*
 *  Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree.
 */

'use strict';

const startVideo = document.getElementById('startVideo');
const callVideo = document.getElementById('callVideo');
const hangupVideo = document.getElementById('hangupVideo');

callVideo.disabled = true;
hangupVideo.disabled = true;

startVideo.onclick = startVideoFunc;
callVideo.onclick = callVideoFunc;
hangupVideo.onclick = hangupVideoFunc;

const startDisplay = document.getElementById('startDisplay');
const callDisplay = document.getElementById('callDisplay');
const hangupDisplay = document.getElementById('hangupDisplay');

startDisplay.disabled = true;
callDisplay.disabled = true;
hangupDisplay.disabled = true;

startDisplay.onclick = startDisplayFunc;
callDisplay.onclick = callDisplayFunc;
hangupDisplay.onclick = hangupDisplayFunc;

const localVideo = document.querySelector('video#local_video');
const localDisplay = document.querySelector('video#local_display');
const remoteVideo = document.querySelector('video#remote_video');
const remoteDisplay = document.querySelector('video#remote_display');

const localAudio = document.querySelector('audio#local_audio');
const remoteAudio = document.querySelector('audio#remote_audio');

window.remoteDisplay = remoteDisplay

let localVideoPeer;
let remoteVideoPeer;

let localDisplayPeer;
let remoteDisplayPeer;

// ================= Start Video
function startVideoFunc() {
  console.log('Requesting local stream');
  startVideo.disabled = true;
  startDisplay.disabled = false;
  
  // local stream
  navigator.mediaDevices
    .getUserMedia({ audio: true, video: true })
    .then(stream => {
      console.log('Received local stream');
      localVideo.srcObject = stream;
      window.localStream = stream;
      callVideo.disabled = false;
      
      let audioStream = new MediaStream();
      localAudio.srcObject = audioStream;
      audioStream.addTrack(stream.getAudioTracks()[0]);
    })
    .catch(e => console.log('getUserMedia() error: ', e));
}

function callVideoFunc() {
  callVideo.disabled = true;
  hangupVideo.disabled = false;
  console.log('Starting calls');
  
  // Create an RTCPeerConnection via the polyfill.
  const servers = null;
  
  localVideoPeer = new RTCPeerConnection(servers);
  remoteVideoPeer = new RTCPeerConnection(servers);
  remoteVideoPeer.ontrack = (e) => {
    if (remoteVideo.srcObject !== e.streams[0]) {
      remoteVideo.srcObject = e.streams[0];
      console.log('remoteVideo: received remote stream');
    }
  };
  localVideoPeer.onicecandidate = iceCallback1Local;
  remoteVideoPeer.onicecandidate = iceCallback1Remote;
  console.log('remoteVideo: created local and remote peer connection objects');
  
  window.localStream.getVideoTracks().forEach(track => localVideoPeer.addTrack(track, window.localStream));
  localVideoPeer.createOffer().then(gotDescription1Local, onCreateSessionDescriptionError);  
}

function hangupVideoFunc() {
  console.log('Ending calls');
  
  localVideoPeer.close();
  remoteVideoPeer.close();  
  localVideoPeer = null;
  remoteVideoPeer = null;
  
  hangupVideo.disabled = true;
  callVideo.disabled = false;
}

// =============== Start Display
function startDisplayFunc() {
  console.log('Requesting local stream');
  startDisplay.disabled = true;
  
  // display stream
  navigator.mediaDevices
    .getDisplayMedia({ video: true })
    .then(stream => {
      localDisplay.srcObject = stream;
      window.displayScreen = stream;
      callDisplay.disabled = false;
    }, error => {
      console.log("Unable to acquire screen capture", error);
    });	  
}

function callDisplayFunc() {
  callDisplay.disabled = true;
  hangupDisplay.disabled = false;
  console.log('Starting calls');
  
  // Create an RTCPeerConnection via the polyfill.
  const servers = null;
  
  localDisplayPeer = new RTCPeerConnection(servers);
  remoteDisplayPeer = new RTCPeerConnection(servers);
  remoteDisplayPeer.ontrack = (e) => {
    if (remoteDisplay.srcObject !== e.streams[0]) {
      remoteDisplay.srcObject = e.streams[0];
      console.log('remoteDisplay: received remote stream');
    }
    
    let audioStream = new MediaStream();
    remoteAudio.srcObject = audioStream;
    audioStream.addTrack(e.streams[0].getAudioTracks()[0]);
  };
  localDisplayPeer.onicecandidate = iceCallback2Local;
  remoteDisplayPeer.onicecandidate = iceCallback2Remote;
  console.log('remoteDisplay: created local and remote peer connection objects');

  // window.localStream.getAudioTracks().forEach(track => localDisplayPeer.addTrack(track, window.localStream));
  window.localStream.getAudioTracks().forEach(track => localDisplayPeer.addTrack(track, window.displayScreen));
  // window.dispalyScreen.getVideoTracks().forEach(track => localDisplayPeer.addTrack(track, window.dispalyScreen));
  localDisplayPeer.addTrack(window.displayScreen.getVideoTracks()[0], window.displayScreen);
  localDisplayPeer.createOffer().then(gotDescription2Local, onCreateSessionDescriptionError);
}

function hangupDisplayFunc() {
  console.log('Ending calls');
  
  localDisplayPeer.close();
  remoteDisplayPeer.close();
  localDisplayPeer = null;
  remoteDisplayPeer = null;
  
  hangupDisplay.disabled = true;
  callDisplay.disabled = false;
}

function onCreateSessionDescriptionError(error) {
  console.log(`Failed to create session description: ${error.toString()}`);
}

function gotDescription1Local(desc) {
  localVideoPeer.setLocalDescription(desc);
  console.log(`Offer from localVideoPeer\n${desc.sdp}`);
  remoteVideoPeer.setRemoteDescription(desc);
  // Since the 'remote' side has no media stream we need
  // to pass in the right constraints in order for it to
  // accept the incoming offer of audio and video.
  remoteVideoPeer.createAnswer().then(gotDescription1Remote, onCreateSessionDescriptionError);
}

function gotDescription1Remote(desc) {
  remoteVideoPeer.setLocalDescription(desc);
  console.log(`Answer from remoteVideoPeer\n${desc.sdp}`);
  localVideoPeer.setRemoteDescription(desc);
}

function gotDescription2Local(desc) {
  localDisplayPeer.setLocalDescription(desc);
  console.log(`Offer from localDisplayPeer\n${desc.sdp}`);
  remoteDisplayPeer.setRemoteDescription(desc);
  // Since the 'remote' side has no media stream we need
  // to pass in the right constraints in order for it to
  // accept the incoming offer of audio and video.
  remoteDisplayPeer.createAnswer().then(gotDescription2Remote, onCreateSessionDescriptionError);
}

function gotDescription2Remote(desc) {
  remoteDisplayPeer.setLocalDescription(desc);
  console.log(`Answer from remoteDisplayPeer\n${desc.sdp}`);
  localDisplayPeer.setRemoteDescription(desc);
}

function iceCallback1Local(event) {
  handleCandidate(event.candidate, remoteVideoPeer, 'remoteVideoPeer: ', 'local');
}

function iceCallback1Remote(event) {
  handleCandidate(event.candidate, localVideoPeer, 'remoteVideoPeer: ', 'remote');
}

function iceCallback2Local(event) {
  handleCandidate(event.candidate, remoteDisplayPeer, 'remoteDisplayPeer: ', 'local');
}

function iceCallback2Remote(event) {
  handleCandidate(event.candidate, localDisplayPeer, 'remoteDisplayPeer: ', 'remote');
}

function handleCandidate(candidate, dest, prefix, type) {
  dest.addIceCandidate(candidate)
      .then(onAddIceCandidateSuccess, onAddIceCandidateError);
  console.log(`${prefix}New ${type} ICE candidate: ${candidate ? candidate.candidate : '(null)'}`);
}

function onAddIceCandidateSuccess() {
  console.log('AddIceCandidate success.');
}

function onAddIceCandidateError(error) {
  console.log(`Failed to add ICE candidate: ${error.toString()}`);
}
